<template>
  <div class="online-users-container">
    <!-- 页面标题区域 -->
    <div class="page-header-wrapper">
      <div class="page-title-section">
        <h1 class="page-title">在线用户管理</h1>
        <p class="page-description">实时监控在线用户状态，管理用户会话和分析使用统计</p>
      </div>
      <div class="page-actions-section">
        <button @click="getList" :disabled="loading" class="action-btn primary">
          <i class="fas fa-sync mr-2" :class="{ 'animate-spin': loading }"></i>
          <span>刷新数据</span>
        </button>
        <button @click="toggleStatsView" class="action-btn secondary">
          <i class="fas fa-chart-bar mr-2" v-if="!showStats"></i>
          <i class="fas fa-list mr-2" v-else></i>
          <span>{{ showStats ? '列表视图' : '统计视图' }}</span>
        </button>
      </div>
    </div>

    <!-- 统计概览卡片 -->
    <div class="stats-overview-section">
      <div class="stats-grid">
        <div class="stat-card">
          <div class="stat-content">
            <div class="stat-icon total">
              <i class="fas fa-users"></i>
            </div>
            <div class="stat-info">
              <div class="stat-value">{{ detailStats?.totalCount || total || 0 }}</div>
              <div class="stat-label">在线用户总数</div>
            </div>
          </div>
        </div>

        <div class="stat-card">
          <div class="stat-content">
            <div class="stat-icon active">
              <i class="fas fa-user-check"></i>
            </div>
            <div class="stat-info">
              <div class="stat-value">{{ detailStats?.activeCount || 0 }}</div>
              <div class="stat-label">活跃用户</div>
              <div class="stat-desc">最近5分钟活动</div>
            </div>
          </div>
        </div>

        <div class="stat-card">
          <div class="stat-content">
            <div class="stat-icon idle">
              <i class="fas fa-user-clock"></i>
            </div>
            <div class="stat-info">
              <div class="stat-value">{{ detailStats?.idleCount || 0 }}</div>
              <div class="stat-label">空闲用户</div>
              <div class="stat-desc">超过5分钟无活动</div>
            </div>
          </div>
        </div>

        <div class="stat-card">
          <div class="stat-content">
            <div class="stat-icon sessions">
              <i class="fas fa-laptop"></i>
            </div>
            <div class="stat-info">
              <div class="stat-value">{{ mySessions || 0 }}</div>
              <div class="stat-label">我的会话</div>
           <div class="stat-desc">
             平均{{ (detailStats?.averageOnlineMinutes || 0).toFixed(1) }}分钟在线
           </div>
            </div>
          </div>
        </div>
      </div>
    </div>

    <!-- 图表分析区域 (仅在统计视图时显示) -->
    <div v-if="showStats && sessionDistribution" class="charts-section">
      <div class="charts-grid">
        <div class="chart-panel">
          <h3 class="chart-title">设备类型分布</h3>
          <div class="chart-container">
            <div class="chart-item" v-for="(item, key) in deviceData" :key="key">
              <div class="chart-label">{{ item.label }}</div>
              <div class="chart-bar">
                <div class="chart-progress" :style="{ width: item.percentage + '%' }"></div>
              </div>
              <div class="chart-value">{{ item.value }}</div>
            </div>
          </div>
        </div>

        <div class="chart-panel">
          <h3 class="chart-title">浏览器分布</h3>
          <div class="chart-container">
            <div class="chart-item" v-for="(item, key) in browserData" :key="key">
              <div class="chart-label">{{ item.label }}</div>
              <div class="chart-bar">
                <div class="chart-progress" :style="{ width: item.percentage + '%' }"></div>
              </div>
              <div class="chart-value">{{ item.value }}</div>
            </div>
          </div>
        </div>

        <div class="chart-panel">
          <h3 class="chart-title">登录时段分布</h3>
          <div class="chart-container">
            <div class="chart-item" v-for="(item, key) in timeData" :key="key">
              <div class="chart-label">{{ item.label }}</div>
              <div class="chart-bar">
                <div class="chart-progress" :style="{ width: item.percentage + '%' }"></div>
              </div>
              <div class="chart-value">{{ item.value }}</div>
            </div>
          </div>
        </div>
      </div>
    </div>

    <!-- 视图控制和用户列表 -->
    <div class="users-list-section">
      <div class="list-header">
        <h3 class="list-title">在线用户列表</h3>
        <div class="view-controls">
          <div class="view-scope-selector">
            <label>视图范围:</label>
            <div class="radio-group">
              <label class="radio-option" :class="{ active: viewScope === 'global' }">
                <input type="radio" v-model="viewScope" value="global" v-permission="'auth:session:all-list'" />
                <span>全局</span>
              </label>
              <label class="radio-option" :class="{ active: viewScope === 'tenant' }">
                <input type="radio" v-model="viewScope" value="tenant" v-permission="'auth:session:tenant-list'" />
                <span>租户</span>
              </label>
              <label class="radio-option" :class="{ active: viewScope === 'mine' }">
                <input type="radio" v-model="viewScope" value="mine" />
                <span>我的</span>
              </label>
            </div>
          </div>
        </div>
      </div>

      <div class="bg-panel radius-lg p-0">
        <el-table
          v-loading="loading"
          :data="detailUserList.length > 0 ? detailUserList : onlineUserList"
          row-key="sessionId"
          border
          style="width: 100%"
        >
          <el-table-column prop="username" label="用户名" min-width="120" />
          <el-table-column prop="nickname" label="昵称" min-width="120" />
          <el-table-column label="IP地址" width="130">
            <template #default="{ row }">
              {{ row.clientIp || row.ip || '-' }}
            </template>
          </el-table-column>
          <el-table-column label="登录地点" min-width="150">
            <template #default="{ row }">
              {{ row.loginLocation || row.location || '-' }}
            </template>
          </el-table-column>
          <el-table-column prop="deptName" label="部门" min-width="120" />
          <el-table-column label="角色" min-width="120">
            <template #default="{ row }">
              <span v-if="row.roleNames && row.roleNames.length > 0">
                {{ row.roleNames.join(', ') }}
              </span>
              <span v-else>-</span>
            </template>
          </el-table-column>
          <el-table-column prop="browser" label="浏览器/设备" min-width="150">
            <template #default="{ row }">
              <div>
                <div>{{ row.browser || row.userAgent || 'Unknown' }}</div>
                <div class="text-xs text-gray-500">{{ row.os || row.deviceType || 'Unknown' }}</div>
              </div>
            </template>
          </el-table-column>
          <el-table-column prop="loginTime" label="登录时间" width="160" />
          <el-table-column prop="lastActiveTime" label="最后活跃" width="160" />
          <el-table-column label="在线时长" width="100">
            <template #default="{ row }">
              {{ formatDuration(row.onlineMinutes || row.sessionDurationMinutes) }}
            </template>
          </el-table-column>
          <el-table-column label="剩余时间" width="120">
            <template #default="{ row }">
              {{ formatSeconds(row.remainingSeconds) }}
            </template>
          </el-table-column>
          <el-table-column label="状态" width="80">
            <template #default="{ row }">
              <el-tag :type="(row.isActive || row.sessionActive !== false) ? 'success' : 'warning'" size="small">
                {{ (row.isActive || row.sessionActive !== false) ? '活跃' : '空闲' }}
              </el-tag>
            </template>
          </el-table-column>
          <el-table-column label="操作" width="280" align="center" fixed="right">
            <template #default="{ row }">
<!--              <el-button-->
<!--                type="primary"-->
<!--                size="small"-->
<!--                @click="handleRefreshPermissions(row)"-->
<!--                v-permission="'auth:user:refresh-permissions'"-->
<!--              >-->
              <el-button
                  type="primary"
                  size="small"
                  @click="handleRefreshPermissions(row)"
              >
                刷新权限
              </el-button>
              <el-button
                type="danger"
                size="small"
                :icon="SwitchButton"
                @click="handleForceLogout(row)"
                v-permission="'auth:session:terminate'"
              >
                强退
              </el-button>
<!--              <el-button-->
<!--                type="warning"-->
<!--                size="small"-->
<!--                @click="handleBanUser(row)"-->
<!--                v-permission="'auth:user:ban'"-->
<!--              >-->
              <el-button
                  type="warning"
                  size="small"
                  @click="handleBanUser(row)"
              >
                封禁
              </el-button>
            </template>
          </el-table-column>
        </el-table>

        <div class="d-flex justify-between items-center p-4">
          <el-pagination
            v-show="total > 0"
            :current-page="queryParams.current"
            :page-size="queryParams.size"
            :total="total"
            :page-sizes="[10, 20, 50, 100]"
            layout="total, sizes, prev, pager, next, jumper"
            @size-change="handleSizeChange"
            @current-change="handleCurrentChange"
          />
        </div>
      </div>
    </div>
  </div>
</template>

<script setup lang="ts">
import { ref, reactive, computed, onMounted, watch } from 'vue'
import { ElMessage, ElMessageBox } from 'element-plus'
import {
  Refresh,
  SwitchButton,
  User
} from '@element-plus/icons-vue'
import type { OnlineUser } from '@/types/system'
import { authApi } from '@/api/auth'

// 响应式数据
const loading = ref(false)
const onlineUserList = ref<OnlineUser[]>([])
const total = ref(0)
const mySessions = ref(0)
const viewScope = ref<'global' | 'tenant' | 'mine'>('tenant')
const showStats = ref(false)

const queryParams = reactive({
  current: 1,
  size: 20
})

// 详细统计数据 - 来自API响应
const detailStats = ref({
  totalCount: 0,
  activeCount: 0,
  idleCount: 0,
  todayLoginCount: 0,
  averageOnlineMinutes: 0,
  statisticTime: ''
})

// 详细用户列表 - 来自API响应
const detailUserList = ref([])

// 会话分布数据 - 来自API响应
const sessionDistribution = ref(null)

// 计算属性 - 设备分布数据
const deviceData = computed(() => {
  if (!sessionDistribution.value?.deviceStats) return []
  const stats = sessionDistribution.value.deviceStats
  const total = stats.desktopCount + stats.mobileCount + stats.tabletCount + stats.unknownCount

  if (total === 0) return []

  return [
    { label: '桌面端', value: stats.desktopCount, percentage: (stats.desktopCount / total) * 100 },
    { label: '移动端', value: stats.mobileCount, percentage: (stats.mobileCount / total) * 100 },
    { label: '平板', value: stats.tabletCount, percentage: (stats.tabletCount / total) * 100 },
    { label: '未知', value: stats.unknownCount, percentage: (stats.unknownCount / total) * 100 }
  ].filter(item => item.value > 0)
})

// 计算属性 - 浏览器分布数据
const browserData = computed(() => {
  if (!sessionDistribution.value?.browserStats) return []
  const stats = sessionDistribution.value.browserStats
  const total = stats.chromeCount + stats.firefoxCount + stats.safariCount +
               stats.edgeCount + stats.ieCount + stats.otherCount

  if (total === 0) return []

  return [
    { label: 'Chrome', value: stats.chromeCount, percentage: (stats.chromeCount / total) * 100 },
    { label: 'Firefox', value: stats.firefoxCount, percentage: (stats.firefoxCount / total) * 100 },
    { label: 'Safari', value: stats.safariCount, percentage: (stats.safariCount / total) * 100 },
    { label: 'Edge', value: stats.edgeCount, percentage: (stats.edgeCount / total) * 100 },
    { label: 'IE', value: stats.ieCount, percentage: (stats.ieCount / total) * 100 },
    { label: '其他', value: stats.otherCount, percentage: (stats.otherCount / total) * 100 }
  ].filter(item => item.value > 0)
})

// 时间分布数据 - 来自API
const timeData = computed(() => {
  if (!sessionDistribution.value?.timeStats) return []
  const stats = sessionDistribution.value.timeStats
  const total = stats.morningCount + stats.afternoonCount + stats.eveningCount + stats.nightCount

  if (total === 0) return []

  return [
    { label: '上午(6-12)', value: stats.morningCount, percentage: (stats.morningCount / total) * 100 },
    { label: '下午(12-18)', value: stats.afternoonCount, percentage: (stats.afternoonCount / total) * 100 },
    { label: '晚上(18-24)', value: stats.eveningCount, percentage: (stats.eveningCount / total) * 100 },
    { label: '深夜(0-6)', value: stats.nightCount, percentage: (stats.nightCount / total) * 100 }
  ].filter(item => item.value > 0)
})

// 方法
const getList = async () => {
  loading.value = true
  try {
    const countResp = await authApi.getOnlineUserCount()
    total.value = Number(countResp?.data ?? 0)

    // 根据选择的视图加载会话
    let sessionsResp: any
    if (viewScope.value === 'global') {
      sessionsResp = await authApi.getAllSessions({ limit: queryParams.size })
    } else if (viewScope.value === 'tenant') {
      sessionsResp = await authApi.getTenantSessions({ limit: queryParams.size })
    } else {
      sessionsResp = await authApi.getUserSessions()
    }
    const list: any[] = Array.isArray(sessionsResp?.data) ? sessionsResp.data as any[] : []
    // 🔧 适配新的SessionInfo字段名
    onlineUserList.value = list.map((s: any) => ({
      sessionId: s.sessionId,
      userId: s.userId,
      username: s.username || s.userId || '-',
      nickname: s.nickname || '-',
      deptName: s.deptName || '-',
      roleNames: s.roleNames || [],
      ip: s.clientIp || '-',                    // ✅ 使用新字段名
      location: s.loginLocation || '-',
      browser: s.userAgent || s.deviceInfo || '-',  // ✅ 使用新字段名
      os: s.osInfo || '-',
      loginTime: s.createTime || '-',           // ✅ 使用新字段名
      lastAccessTime: s.lastActiveTime || '-',  // ✅ 使用新字段名
      tenantId: s.tenantId,
      deviceInfo: s.deviceInfo,
      sessionDurationMinutes: s.sessionDurationMinutes,
      onlineMinutes: s.onlineMinutes,
      remainingSeconds: s.tokenTimeout,         // ✅ 映射tokenTimeout为remainingSeconds
      inactive: s.inactive,
      deviceType: s.deviceType,
      sessionActive: s.sessionActive
    }))
    // 刷新统计
    total.value = onlineUserList.value.length
    // 计算我的会话数量（按 userId == 当前登录用户）
    try {
      const me = JSON.parse(localStorage.getItem('kexio-user-info') || '{}')
      const myId = me?.userId
      mySessions.value = myId ? onlineUserList.value.filter(x => x.userId === myId).length : 0
    } catch {}

    // 获取详细统计数据
    try {
      const detailResponse = await authApi.getOnlineUserDetails(true)
      if (detailResponse.data) {
        detailStats.value = detailResponse.data.statistics
        detailUserList.value = detailResponse.data.users || []
        sessionDistribution.value = detailResponse.data.sessionDistribution
      }
    } catch (error) {
      console.warn('获取详细统计数据失败:', error)
    }
  } catch (error) {
    ElMessage.error('获取在线用户失败')
  } finally {
    loading.value = false
  }
}

const toggleStatsView = () => {
  showStats.value = !showStats.value
}

const handleSizeChange = (size: number) => {
  queryParams.size = size
  getList()
}

const handleCurrentChange = (current: number) => {
  queryParams.current = current
  getList()
}

const handleForceLogout = async (row: OnlineUser) => {
  try {
    await ElMessageBox.confirm(
      `确定要强制用户"${row.username}"下线吗？`,
      '提示',
      {
        confirmButtonText: '确定',
        cancelButtonText: '取消',
        type: 'warning'
      }
    )

    await authApi.terminateSession(row.sessionId)
    ElMessage.success('强制下线成功')
    getList()
  } catch (error) {
    if (error !== 'cancel') {
      ElMessage.error('强制下线失败')
    }
  }
}

const handleBanUser = async (row: OnlineUser) => {
  try {
    // 使用自定义对话框选择封禁时长和原因
    const result = await ElMessageBox.confirm(
      `
      <div style="margin-bottom: 15px;">
        <p style="margin-bottom: 10px;">确定要封禁用户 <strong>"${row.username}"</strong> 吗？</p>
        <p style="font-size: 13px; color: #666;">封禁后用户将被强制下线且无法登录</p>
      </div>
      `,
      '封禁用户',
      {
        confirmButtonText: '永久封禁',
        cancelButtonText: '取消',
        type: 'warning',
        dangerouslyUseHTMLString: true,
        distinguishCancelAndClose: true,
        showCancelButton: true,
        showClose: true
      }
    )

    // 弹出输入框要求输入封禁原因
    const { value: reason } = await ElMessageBox.prompt(
      '请输入封禁原因：',
      '封禁原因',
      {
        confirmButtonText: '确定',
        cancelButtonText: '取消',
        inputPlaceholder: '例如：违反使用规定',
        inputValue: '违反使用规定'
      }
    )

    // -1表示永久封禁
    await authApi.banUser(row.userId, reason || '违反使用规定', -1)
    ElMessage.success('用户已永久封禁并强制下线')
    getList()
  } catch (error) {
    if (error !== 'cancel' && error !== 'close') {
      ElMessage.error('封禁用户失败')
    }
  }
}

const handleRefreshPermissions = async (row: OnlineUser) => {
  try {
    await ElMessageBox.confirm(
      `确定要刷新用户"${row.username}"的权限吗？这将使该用户的权限变更立即生效，无需下线重新登录。`,
      '刷新权限',
      {
        confirmButtonText: '确定',
        cancelButtonText: '取消',
        type: 'info'
      }
    )

    await authApi.refreshUserPermissions(row.userId)
    ElMessage.success('权限刷新成功，用户下次请求将使用新权限')
  } catch (error) {
    if (error !== 'cancel') {
      ElMessage.error('刷新权限失败')
    }
  }
}

// 格式化时长
const formatDuration = (minutes: number) => {
  if (!minutes || minutes < 1) return '< 1分钟'
  if (minutes < 60) return `${Math.round(minutes)}分钟`
  const hours = Math.floor(minutes / 60)
  const mins = Math.round(minutes % 60)
  return `${hours}小时${mins}分钟`
}

// 格式化剩余时间（秒）
const formatSeconds = (seconds: number) => {
  if (!seconds || seconds < 1) return '即将过期'
  if (seconds < 60) return `${seconds}秒`
  if (seconds < 3600) return `${Math.floor(seconds / 60)}分钟`
  if (seconds < 86400) {
    const hours = Math.floor(seconds / 3600)
    const mins = Math.floor((seconds % 3600) / 60)
    return `${hours}小时${mins}分钟`
  }
  const days = Math.floor(seconds / 86400)
  const hours = Math.floor((seconds % 86400) / 3600)
  return `${days}天${hours}小时`
}

// 监听视图范围变化，自动刷新数据
watch(viewScope, () => {
  getList()
})

// 生命周期
onMounted(() => {
  getList()
})
</script>

<style scoped>
/* 页面容器 */
.online-users-container {
  padding: 2rem;
  background: linear-gradient(135deg, #f8fafc 0%, #e2e8f0 100%);
  min-height: 100vh;
}

/* 页面标题区域 */
.page-header-wrapper {
  background: rgba(255, 255, 255, 0.95);
  border-radius: 20px;
  padding: 2.5rem;
  margin-bottom: 3rem;
  box-shadow:
    0 10px 40px rgba(0, 0, 0, 0.08),
    0 2px 8px rgba(0, 0, 0, 0.04);
  backdrop-filter: blur(20px);
  border: 1px solid rgba(255, 255, 255, 0.3);
}

.page-title-section {
  margin-bottom: 2rem;
}

.page-title {
  font-size: 2.5rem;
  font-weight: 700;
  margin-bottom: 0.75rem;
  background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
  -webkit-background-clip: text;
  -webkit-text-fill-color: transparent;
  background-clip: text;
}

.page-description {
  font-size: 1.1rem;
  color: #64748b;
  line-height: 1.6;
}

.page-actions-section {
  display: flex;
  gap: 1.25rem;
  flex-wrap: wrap;
}

/* 按钮样式 */
.action-btn {
  padding: 0.75rem 1.5rem;
  border-radius: 12px;
  border: none;
  font-weight: 500;
  font-size: 0.95rem;
  display: flex;
  align-items: center;
  gap: 0.5rem;
  transition: all 0.3s ease;
  cursor: pointer;
  color: white;
  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
}

.action-btn.primary {
  background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
}

.action-btn.secondary {
  background: linear-gradient(135deg, #cbd5e0 0%, #a0aec0 100%);
  color: #4a5568;
}

.action-btn:hover:not(:disabled) {
  transform: translateY(-2px);
  box-shadow: 0 6px 20px rgba(0, 0, 0, 0.2);
}

.action-btn:disabled {
  opacity: 0.5;
  cursor: not-allowed;
  transform: none;
}

/* 统计概览区域 */
.stats-overview-section {
  margin-bottom: 3rem;
}

.stats-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
  gap: 2rem;
}

.stat-card {
  background: rgba(255, 255, 255, 0.95);
  border-radius: 20px;
  padding: 2rem;
  box-shadow:
    0 10px 40px rgba(0, 0, 0, 0.08),
    0 2px 8px rgba(0, 0, 0, 0.04);
  backdrop-filter: blur(20px);
  border: 1px solid rgba(255, 255, 255, 0.3);
  transition: all 0.3s ease;
}

.stat-card:hover {
  transform: translateY(-4px);
  box-shadow:
    0 20px 60px rgba(0, 0, 0, 0.12),
    0 4px 16px rgba(0, 0, 0, 0.08);
}

.stat-content {
  display: flex;
  align-items: center;
  gap: 1.5rem;
}

.stat-icon {
  width: 4rem;
  height: 4rem;
  border-radius: 16px;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 1.5rem;
  color: white;
}

.stat-icon.total {
  background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
}

.stat-icon.active {
  background: linear-gradient(135deg, #48bb78 0%, #38a169 100%);
}

.stat-icon.idle {
  background: linear-gradient(135deg, #ed8936 0%, #dd6b20 100%);
}

.stat-icon.sessions {
  background: linear-gradient(135deg, #4299e1 0%, #3182ce 100%);
}

.stat-info {
  flex: 1;
}

.stat-value {
  font-size: 2.5rem;
  font-weight: 700;
  color: #1a202c;
  line-height: 1;
  margin-bottom: 0.5rem;
}

.stat-label {
  font-size: 1rem;
  color: #4a5568;
  margin-bottom: 0.25rem;
  font-weight: 500;
}

.stat-desc {
  font-size: 0.85rem;
  color: #718096;
}

/* 图表分析区域 */
.charts-section {
  margin-bottom: 3rem;
}

.charts-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(350px, 1fr));
  gap: 2rem;
}

.chart-panel {
  background: rgba(255, 255, 255, 0.95);
  border-radius: 20px;
  padding: 2rem;
  box-shadow:
    0 10px 40px rgba(0, 0, 0, 0.08),
    0 2px 8px rgba(0, 0, 0, 0.04);
  backdrop-filter: blur(20px);
  border: 1px solid rgba(255, 255, 255, 0.3);
}

.chart-title {
  font-size: 1.25rem;
  font-weight: 600;
  color: #2d3748;
  margin-bottom: 1.5rem;
}

.chart-container {
  display: flex;
  flex-direction: column;
  gap: 1rem;
}

.chart-item {
  display: flex;
  align-items: center;
  gap: 1rem;
}

.chart-label {
  width: 80px;
  font-size: 0.9rem;
  color: #4a5568;
  font-weight: 500;
}

.chart-bar {
  flex: 1;
  height: 10px;
  background: #f1f5f9;
  border-radius: 8px;
  overflow: hidden;
}

.chart-progress {
  height: 100%;
  background: linear-gradient(90deg, #667eea, #764ba2);
  border-radius: 8px;
  transition: width 0.6s ease;
}

.chart-value {
  width: 40px;
  text-align: right;
  font-size: 0.9rem;
  color: #2d3748;
  font-weight: 600;
}

/* 用户列表区域 */
.users-list-section {
  background: rgba(255, 255, 255, 0.95);
  border-radius: 20px;
  padding: 2.5rem;
  box-shadow:
    0 10px 40px rgba(0, 0, 0, 0.08),
    0 2px 8px rgba(0, 0, 0, 0.04);
  backdrop-filter: blur(20px);
  border: 1px solid rgba(255, 255, 255, 0.3);
}

.list-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: 2rem;
  padding-bottom: 1.5rem;
  border-bottom: 1px solid #e2e8f0;
}

.list-title {
  font-size: 1.5rem;
  font-weight: 600;
  color: #2d3748;
}

.view-controls {
  display: flex;
  gap: 2rem;
  align-items: center;
}

.view-scope-selector {
  display: flex;
  gap: 1rem;
  align-items: center;
}

.view-scope-selector label {
  font-size: 0.9rem;
  color: #4a5568;
  font-weight: 500;
}

.radio-group {
  display: flex;
  gap: 0.5rem;
}

.radio-option {
  padding: 0.5rem 1rem;
  border-radius: 8px;
  border: 1px solid #e2e8f0;
  background: white;
  cursor: pointer;
  transition: all 0.3s ease;
  display: flex;
  align-items: center;
  gap: 0.5rem;
}

.radio-option input[type="radio"] {
  display: none;
}

.radio-option span {
  font-size: 0.9rem;
  color: #4a5568;
}

.radio-option.active {
  background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
  border-color: #667eea;
  color: white;
}

.radio-option.active span {
  color: white;
}

.radio-option:hover:not(.active) {
  background: #f7fafc;
  border-color: #cbd5e0;
}

/* 响应式设计 */
@media (max-width: 768px) {
  .online-users-container {
    padding: 1rem;
  }

  .page-header-wrapper {
    padding: 2rem;
  }

  .page-title {
    font-size: 2rem;
  }

  .stats-grid {
    grid-template-columns: 1fr;
    gap: 1.5rem;
  }

  .charts-grid {
    grid-template-columns: 1fr;
  }

  .list-header {
    flex-direction: column;
    align-items: flex-start;
    gap: 1rem;
  }
}
</style>
